在App Inventor中使用较新版本的Android SDK时支持较旧的设备

开始于:JoséDominguezjosmasflores@gmail.com)于2013年7月1日

介绍

目前的MinSDK

问题和解决方案

问题

解决方案

实施解决方案

介绍

App Inventor支持API Level 4,Platform 1.5版(截至2016年2月)的所有设备。较新版本的Android SDK中添加的某些功能可供较新设备的用户使用,但仍需要在较旧的设备中妥善处理。一个例子是 在Web  组件中使用cookie API级别9(Gingerbread)上添加了Cookie支持,使用App Inventor开发的应用程序可以在运行该级别(或更高级别)的设备中使用它们,同时在低于9的设备中显示短时间通知,说明特定的功能无法使用。

目前的MinSDK

android清单文件在Compiler.java中生成目前应用程序默认为Api Level 4,Companion也是使用此版本构建的。

如果您从源代码编译服务器,您将在“实验”类别中看到名为Firebase的其他组件。使用Firebase组件时,必须将minSDK 重置  为级别10。

问题和解决方案

在大多数系统中,向后兼容性是期望的质量,尽管它通常伴随着一些权衡。App Inventor中使用的解决方案类似于 此(相当旧的)博客帖子中解释包装类

问题

添加到较新版本SDK的类将无法在运行较旧堆栈的设备中使用,因此,如果在运行时使用这些类,则应用程序在尝试执行时会崩溃(更多关于博客文章中的链接和类初始化)以上链接)。这个问题有不同的方法,从不允许在设备中安装应用程序,通过声明最低SDK,允许以不同的方式安装和处理设备,这取决于他们是否可以使用SDK的某些部分。这是App Inventor中的工作方式,它提供了许多包装类,允许组件开发人员决定在某些功能不可用时该怎么做。下一节将提供几个如何执行此操作的示例。

解决方案

解决方案是使用帮助程序类。它们的名称基于它们所代表的Android版本。例如:DonutUtil.javaEclairUtil.javaFroyoUitl.javaGingerbreadUtil.java  和其他(对于较新的设备)都位于components / runtime / util /这些类封装了仅存在于特定API级别(和更高级别)的特定行为。使组件类使用这些实用程序类之一而不是直接使用API​​类,允许围绕某些设备中特定的非可用功能块的约束进行额外设计。让我们看几个例子: 

Web组件 中的GingerbreadUtil Gingerbread中添加了Cookies支持(API级别9)。在文档中我们可以看到这个(见截图):http//developer.android.com/reference/java/net/CookieManager.html

右上角的第二行显示:'在API级别9中添加'。9级是Gingerbread(咨询API级别)。

可以在Web组件中看到以下代码

cookieHandler =(SdkLevel.getLevel()> = SdkLevel.LEVEL_GINGERBREAD)

    ?GingerbreadUtil.newCookieManager()

    : 空值;

我们的想法是,如果设备支持使用cookie,那么我们返回一个Cookie管理器来处理它(由Util类提供的cookie管理器)。如果没有,我们将cookieHandler初始化为null。稍后在代码中,检查将处理旧设备的空值。在这种情况下,如下面的代码所示,向用户显示关于不支持的功能的适当消息。

if(allowCookies && cookieHandler == null){

  form.dispatchErrorOccurredEvent(this,“AllowCookies”,

    ErrorMessages.ERROR_FUNCTIONALITY_NOT_SUPPORTED_WEB_COOKIES);

}

运行Gingerbread或更高版本的设备与运行Froyo或更低版本的设备之间的主要行为差异在于,具有第一个设备的用户将自动使用cookie,而第二类设备的用户将在其屏幕中看到一条消息,说明他们的设备不支持cookie(这由通过Form类调度的错误消息处理)。

通过 在OrientationSensor  组件中使用FroyoUitl.java可以在App Inventor代码库中找到不同的示例代码如下:

  private int getScreenRotation(){

    显示屏=

        ((WindowManager)form.getSystemService(Context.WINDOW_SERVICE))。

        getDefaultDisplay();

    if(SdkLevel.getLevel()> = SdkLevel.LEVEL_FROYO){

      return FroyoUtil.getRotation(display);

    } else {

      return display.getOrientation();

    }

  }

根据文档,随着API级别8(Froyo)的引入,方法getOrientation已被弃用:

 应该使用方法getRotation(),但这仅适用于8级及更高级别:

FroyoUtil.java  将方法getRotation定义为:

  public static int getRotation(Display display){

    return display.getRotation();

  }

运行Froyo或更高版本的设备与运行Eclair或更低版本的设备之间的主要行为差异在于,具有第一个设备的用户将更准确地报告其设备的方向值(根据文档的返回轮换屏幕从其“自然”方向')比第二类设备的用户。

代码中有更多示例,例如DonutUtil.java  为以前版本的Android堆栈中不可用的动画添加了一些处理。 

实施解决方案

实现解决方案需要两个步骤,第一个是选择应用程序在不受支持的设备中的行为,第二个是通过代码库中的一个Uitl类实现解决方案。

通过一个间接层调用会增加一点点开销,但这不应该是一个大问题。

为不同设备的用户提供不同的体验并不理想,但遗憾的是,没有办法绕过它,并且最好不允许在某些设备中安装应用程序(除非功能对应用程序如此重要,否则它不会没有它就有意义!)。更改SDK级别可以在Compiler.java中完成,但如果没有咨询团队,就不应该这样做。

注意:源中可能存在可以以不同方式处理SDK级别差异的位置。本文档中描述的那个是首选的。

原文